package etcd

import (
	"context"
	"mediumkube/pkg/configurations"
	"mediumkube/pkg/utils"
	"strings"

	"go.etcd.io/etcd/api/v3/mvccpb"
	clientv3 "go.etcd.io/etcd/client/v3"
)

type ETCDErrType uint

var (
	client_v3 *clientv3.Client
	err       error

	Unknown      ETCDErrType = 0
	KeyNotExists ETCDErrType = 1
	KeyNotFound  ETCDErrType = 2
)

func NewV3ClientOrDie() *clientv3.Client {
	if client_v3 == nil {
		config := configurations.Config().Overlay
		client_v3, err = clientv3.NewFromURL(utils.EtcdEp(config.Master, config.EtcdPort))
		utils.CheckErr(err)
	}

	return client_v3
}

func ParseErr(e error) ETCDErrType {
	if strings.Contains(e.Error(), "already exists") {
		return KeyNotExists
	} else if strings.Contains(e.Error(), "not found") {
		return KeyNotFound
	}
	return Unknown
}

func ETCDV3Put(ctx context.Context, k, v string) (*clientv3.PutResponse, error) {
	v3c := NewV3ClientOrDie()
	return v3c.Put(ctx, k, v)
}

func ETCDV3PutIfNotExists(ctx context.Context, k, v string) error {
	v3c := NewV3ClientOrDie()
	_, err := v3c.Get(ctx, k)
	if err != nil && ParseErr(err) == KeyNotExists {
		_, err = v3c.Put(ctx, k, v)
		return err
	}
	return nil
}

func ETCDV3Get(ctx context.Context, k string) ([]*mvccpb.KeyValue, error) {
	v3c := NewV3ClientOrDie()
	r, err := v3c.Get(ctx, k, clientv3.WithPrefix())
	if err != nil {
		return nil, err
	}
	return r.Kvs, nil
}

func ETCDV3Delete(ctx context.Context, k string) error {
	v3c := NewV3ClientOrDie()
	_, err := v3c.Delete(ctx, k)
	return err
}
